package com.glsc.ngateway.opmanage.service.feign;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import com.glsc.ngateway.common.api.oaflow.dto.*;
import com.glsc.ngateway.common.api.oaflow.dto.oaflow.WorkflowRequestbaseDto;
import com.glsc.ngateway.common.api.oaflow.feign.IFeignOaFlowService;
import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.api.oaflow.resp.CommonResponse;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.*;
import com.glsc.ngateway.common.api.common.dto.PageDataResult;
import com.glsc.ngateway.common.api.common.ex.GatewayException;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.log.XinYiLog;
import com.glsc.ngateway.common.base.domain.oracle.yongyou.Fkzh;
import com.glsc.ngateway.common.base.domain.oracle.yongyou.Skzh;
import com.glsc.ngateway.common.base.repo.mysql.opmanagemain.log.XinYiLogRepo;
import com.glsc.ngateway.common.base.repo.oracle.yongyou.FkzhRepo;
import com.glsc.ngateway.common.base.repo.oracle.yongyou.SkzhRepo;
import com.glsc.ngateway.opmanage.dto.OaBatchUploadFileDto;
import com.glsc.ngateway.opmanage.dto.OaFileDto;
import com.glsc.ngateway.opmanage.service.MailService;
import com.glsc.ngateway.opmanage.service.SystemConfigService;
import com.glsc.ngateway.opmanage.service.other.TradeAccountService;
import com.glsc.ngateway.opmanage.utils.DateUtils;

import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import com.google.common.collect.Lists;

import io.swagger.annotations.ApiParam;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Example;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.*;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: zzp
 * @Date: 2021/4/2
 * @Desc:对接网关等外部接口的服务二次封装，统一返回数据格式、报文结构等
 */
@Service
public class GatewayFeignService {

    private static final Logger logger = LoggerFactory.getLogger(GatewayFeignService.class);

    private static final Integer GATEWAY_RET_CODE_SUCCESS = 0;

    @Resource
    private IFeignOaFlowService eurekaOaFlowFeignService;

    @Resource
    private MailService mailService;

    @Resource
    private SystemConfigService systemConfigService;

    @Resource
    private TradeAccountService tradeAccountService;

    @Resource
    private IFeignOaFlowService iFeignOaFlowService;

    @Resource
    private XinYiLogRepo xinYiLogRepo;

    @Resource
    private FkzhRepo fkzhRepo;

    @Resource
    private SkzhRepo skzhRepo;

    /*
     * 查询流程表单数据
     * */
    public String getRequestData(@ApiParam(required = true, value = "requestId") String requestId) {
        logger.info("开始进行 查询流程表单数据,requestId=" + requestId);
        String ret = eurekaOaFlowFeignService.getRequestData(requestId);
        logger.info("getRequestData接口返回：" + ret);
        return ret;
    }

    public String getRequestDataOrigin(@ApiParam(required = true, value = "requestId") String requestId, @ApiParam(required = true, value = "requestId") String workflowId) {
        logger.info("开始进行 查询流程表单数据,requestId=" + requestId);
        String ret = eurekaOaFlowFeignService.getRequestDataOrigin(requestId, workflowId);
        logger.info("getRequestData接口返回：" + ret);
        return ret;
    }

    public String callXy(@ApiParam(required = true, value = "param") String param) {
        logger.info("开始进行 调用新意接口,param=" + param);
        String ret = eurekaOaFlowFeignService.callXy(param);
        logger.info("getRequestData接口返回：" + ret);
        return ret;
    }

    public List<WorkflowRequestbaseDto> getRequestDataNew(@ApiParam(required = true, value = "param") String requestId) {
        logger.info("开始进行 调用流程节点查询接口,param=" + requestId);
        CommonResponse<List<WorkflowRequestbaseDto>> ret = eurekaOaFlowFeignService.getRequestDataNew(Lists.newArrayList(requestId));
        logger.info("getRequestData接口返回：" + ret);
        return ret.getData();
    }

    /**
     * 新增数字证书，kettle同步，此接口不通
     */
    @Deprecated
    public String addDigitalCertificate(UFyyglzbszzszbDto uFyyglzbszzszbDto) {
        logger.info("开始进行 新增数字证书,uFyyglzbszzszbDto=" + uFyyglzbszzszbDto);
        String ret = eurekaOaFlowFeignService.addDigitalCertificate(uFyyglzbszzszbDto);
        logger.info("新增数字证书addDigitalCertificate接口返回：" + ret);
        return ret;
    }

    /**
     * 创建数字证书到期提醒OA流程
     */
    public String createOaflow4DigitalKeyExpireDateRemind(DigitalKeyCreateOaFlowDto digitalKeyCreateOaFlowDto, String flowId) {
        logger.info("开始进行 创建数字证书到期提醒OA流程,digitalKeyCreateOaFlowDto=" + digitalKeyCreateOaFlowDto);
        String ret = eurekaOaFlowFeignService.createOaFlow(digitalKeyCreateOaFlowDto, flowId);
        logger.info("创建数字证书到期提醒OA流程createOaflow接口返回：" + ret);
        return ret;
    }

    /**
     * 创建oa流程接口
     *
     * @param dataMap
     * @param flowId
     * @return
     */
    public String createOaFlow(Map<String, Object> dataMap, String flowId) {
        logger.info("创建oa流程,请求参数={}" + JSON.toJSONString(dataMap));
        String ret = eurekaOaFlowFeignService.createOaFlow(dataMap, flowId);
        logger.info("创建oa流程,响应结果={}" + JSON.toJSONString(ret));
        return ret;
    }

    /**
     * 创建oa流程接口 以传入的部门和公司信息为准
     *
     * @param dataMap
     * @param flowId
     * @return
     */
    public String createOaFlowWithDeptId(Map<String, Object> dataMap, String flowId) {
        logger.info("创建oa流程,请求参数={}" + JSON.toJSONString(dataMap));
        String ret = eurekaOaFlowFeignService.createOaflowWithDeptId(dataMap, flowId);
        logger.info("创建oa流程,响应结果={}" + JSON.toJSONString(ret));
        return ret;
    }


//    /**
//     * 调用网关批量上传文件service
//     *
//     * @param creator
//     * @param fileList
//     * @return
//     */
//    public String batchUpload(String creator, List<Map<String, Object>> fileList) {
//        Map<String, Object> dataMap = new HashMap<>();
//        dataMap.put("creater", creator);
//        dataMap.put("files", fileList);
//        logger.info("batchUpload批量上传接口返回请求数据：" + dataMap.toString());
//        String retMsg = eurekaAmDocFeignService.batupload(dataMap);
//        logger.info("batchUpload批量上传接口返回报文信息：" + retMsg);
//        return retMsg;
//    }

    /*
     * 检查网关返回数据是否正常
     * */
    private boolean validGatewayResponse(PageDataResult ret) {
        if (null == ret) {
            logger.info("接口返回为空");
            throw GatewayException.error("接口返回为空");
        } else if (ret.getCode() != 0 && ret.getCode() != 18) {//分页返回18是正常
            String errMsg = "接口返回异常，错误码=" + ret.getCode();
            logger.info(errMsg);
            throw GatewayException.error(errMsg);
        } else {
            logger.info("接口返回正常，返回信息=" + ret.toString());
            return true;
        }
    }

    /*
     * 调用OA查询表单数据
     * OA接口正常返回：
     * {"code":0,"data":[{"flowNodeCode":1106974,"flowNode":"结束","requestId":464981,"flowInfos":{"ID":24,"applyNumber":"zgcppslc20210600024","applyDate":"2021-06-10","applicant":"杨昳,yiyang@glsc.com.cn","applicantDepart":"资产管理部/运营管理-运营","applicantComp":"国联证券总部","businessType":"集合标类","productSelect":"1000241","reviewer":"张春蓉","depReviewer":"杨昳","reviewerReply":"发起人意见落实回复","depReviewerReply":"表决已全票“同意”","businessTypeCode":2,"reviewerReplyCode":0,"depReviewerReplyCode":1},"flowStatusType":"3"}],"status":"SUCCESS"}
     * OA接口异常返回数据：
     * {"status":"EXCEPTION","code":17,"msg":"业务异常，查询结果为NULL"}
     * */
    public SynOaTradeSeatDto getOAFormData4TradeSeat(String workflowId, String requestId) throws NoSuchFieldException, IllegalAccessException {
        String retStr = this.getRequestData(requestId);
        logger.info("调用OA查询表单数据交易单元信息返回:" + retStr);

        JSONObject retJSONObject = JSONObject.parseObject(retStr);

        if (StrUtil.isEmpty(retStr) || retJSONObject == null || !GATEWAY_RET_CODE_SUCCESS.equals(retJSONObject.get("code"))) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }

        //查询OA表单数据字段
        String fieldList = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_TRADE_SEAT_FIELD);
        SynOaTradeSeatDto synOaTradeSeatDto = new SynOaTradeSeatDto();
        synOaTradeSeatDto.setWorkflowId(workflowId);
        synOaTradeSeatDto.setRequestId(requestId);


        JSONArray dataJson = retJSONObject.getJSONArray("data");
        JSONObject jsonObject = dataJson.getJSONObject(0);
        JSONObject flowInfosJSONObject = jsonObject.getJSONObject("flowInfos");//表单个性化字段信息

        //表单公共字段解析
        Integer flowNodeCode = jsonObject.getInteger("flowNodeCode");
        synOaTradeSeatDto.setFlowNodeCode(flowNodeCode);

        String workflowName = retJSONObject.getString("workflowName");
        if (StrUtil.isNotEmpty(workflowName)) {
            synOaTradeSeatDto.setWorkflowName(workflowName);
        }
        String flowNode = jsonObject.getString("flowNode");
        if (StrUtil.isNotEmpty(flowNode)) {
            synOaTradeSeatDto.setFlowNode(StrUtil.trim(flowNode));
        }
        String flowStatusType = jsonObject.getString("flowStatusType");
        if (StrUtil.isNotEmpty(flowStatusType)) {
            synOaTradeSeatDto.setFlowStatusType(StrUtil.trim(flowStatusType));
        }

        //配置个性化表单解析
        if (StrUtil.isNotEmpty(fieldList)) {
            String[] detailFormList = fieldList.split(",");
            for (String current : detailFormList) {
                if (flowInfosJSONObject.containsKey(current)) {
                    Field name = synOaTradeSeatDto.getClass().getDeclaredField(current + "");
                    name.setAccessible(true);
                    name.set(synOaTradeSeatDto, flowInfosJSONObject.getString(current));
                    name.setAccessible(false);
                }
            }
        }

        Integer applyDeptId = flowInfosJSONObject.getInteger("applicantDepartId");
        synOaTradeSeatDto.setApplyDeptId(applyDeptId);
        String applyDeptName = flowInfosJSONObject.getString("applicantDepart");
        synOaTradeSeatDto.setApplyDeptName(applyDeptName);
        Integer applyTypeCode = flowInfosJSONObject.getInteger("applyTypeCode");
        synOaTradeSeatDto.setApplyTypeCode(applyTypeCode);
        Integer changeTypeCode = flowInfosJSONObject.getInteger("changeTypeCode");
        synOaTradeSeatDto.setChangeTypeCode(changeTypeCode);

        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap2");
        List<SynOaTradeSeatInfoDto> synOaTradeSeatInfoDtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaTradeSeatInfoDtoList(detailMap, fieldList, synOaTradeSeatInfoDtoList);
        }

        detailMap = flowInfosJSONObject.getJSONArray("detailMap3");
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaTradeSeatInfoDtoList(detailMap, fieldList, synOaTradeSeatInfoDtoList);
        }

        detailMap = flowInfosJSONObject.getJSONArray("detailMap4");
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaTradeSeatInfoDtoList(detailMap, fieldList, synOaTradeSeatInfoDtoList);
        }

        detailMap = flowInfosJSONObject.getJSONArray("detailMap5");
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaTradeSeatInfoDtoList(detailMap, fieldList, synOaTradeSeatInfoDtoList);
        }

        synOaTradeSeatDto.setTradeSeatInfoList(synOaTradeSeatInfoDtoList);

        logger.info("获取OA表单交易单元信息，返回synOaTradeSeatDto:" + synOaTradeSeatDto);
        return synOaTradeSeatDto;
    }

    public void buildSynOaTradeSeatInfoDtoList(JSONArray detailMap, String fieldList, List<SynOaTradeSeatInfoDto> synOaTradeSeatInfoDtoList) throws NoSuchFieldException, IllegalAccessException {
        for (int i = 0; i < detailMap.size(); i++) {
            JSONObject object = detailMap.getJSONObject(i);
            SynOaTradeSeatInfoDto synOaTradeSeatInfoDto = new SynOaTradeSeatInfoDto();
            //配置个性化表单解析
            if (StrUtil.isNotEmpty(fieldList)) {
                String[] detailFormList = fieldList.split(",");
                for (String current : detailFormList) {
                    if (object.containsKey(current)) {
                        Field name = synOaTradeSeatInfoDto.getClass().getDeclaredField(current + "");
                        name.setAccessible(true);
                        name.set(synOaTradeSeatInfoDto, object.getString(current));
                        name.setAccessible(false);
                    }
                }
            }
            String useCompanyId = object.getString("useMemberId");
            synOaTradeSeatInfoDto.setUseCompanyId(useCompanyId);
            String useCompanyName = object.getString("useMember");
            synOaTradeSeatInfoDto.setUseCompanyName(useCompanyName);

            Integer expenseDeptId = object.getInteger("expenseDepartmentId");
            synOaTradeSeatInfoDto.setExpenseDeptId(expenseDeptId);
            String expenseDeptName = object.getString("expenseDepartment");
            synOaTradeSeatInfoDto.setExpenseDeptName(expenseDeptName);
            String state = object.getString("status");
            synOaTradeSeatInfoDto.setState(state);
            String dealDate = object.getString("dealDate");
            if (DictConstant.TRADE_SEAT_STATE_BEGIN.equals(state)) {
                synOaTradeSeatInfoDto.setBeginDate(dealDate);
            } else if (DictConstant.TRADE_SEAT_STATE_END.equals(state)) {
                synOaTradeSeatInfoDto.setEndDate(dealDate);
            }
            String isExpense = object.getString("isExpense");
            if (StrUtil.isNotEmpty(isExpense)) {
                if (DictConstant.IS_EXPENCE_YES.equals(isExpense)) {
                    String afterExpenseDesc = object.getString("afterExpenseDesc");
                    if (StrUtil.isEmpty(synOaTradeSeatInfoDto.getExpenseDesc())) {
                        synOaTradeSeatInfoDto.setExpenseDesc(afterExpenseDesc);
                    }
                } else {
                    String afterExpenseDepartmentId = object.getString("afterExpenseDepartmentId");
                    String afterExpenseDepartment = object.getString("afterExpenseDepartment");
                    if (null == synOaTradeSeatInfoDto.getExpenseDeptId()) {
                        synOaTradeSeatInfoDto.setExpenseDeptId(afterExpenseDepartmentId == null ? null : Integer.valueOf(afterExpenseDepartmentId));
                    }
                    if (StrUtil.isEmpty(synOaTradeSeatInfoDto.getExpenseDeptName())) {
                        synOaTradeSeatInfoDto.setExpenseDeptName(afterExpenseDepartment);
                    }
                }
            }

            synOaTradeSeatInfoDtoList.add(synOaTradeSeatInfoDto);
        }
    }

    /**
     * 获取【08.交易运营事项用印审批OA流程】中的文件信息
     * <p>
     * {"code":0,"data":[{"requestName":"08.交易运营事项用印审批OA流程-苏伟-2024-01-22（附件:数字国联2023年总结）","workFlowTypeName":"交易运营事项用印审批OA流程","flowNodeCode":233444,"workFlowId":210106,"flowNode":"结束","requestId":1124598,"flowInfos":{"ID":2983,"applyNumber":"jyyysxyysplc20240100001","applyDate":"2024-01-22","applicant":"苏伟,","applicantDepart":"信息技术总部/综合管理组","hopeFinishTime":"2024-01-22","explain":"123","appendix":"","transOperType":"场外期权","transOperTypeCode":0,"transOperMatter":"1.SAC主补协议、收益凭证材料（认购协议、产品说明书、风险揭示书）","transOperMatterCode":0,"sealFile":"http://10.192.0.12:8080/api/gl/getAttach?attach=MTIxNzI1Mg==","applicantDepartId":"92","applicantCompId":"21","sealFileFileInfo":[{"fileName":"数字国联2023年总结.pdf","id":"1217252","url":"http://10.192.0.12:8080/api/gl/getAttach?attach=MTIxNzI1Mg=="}],"appendix_file_names":"","appendixFileInfo":[]},"workflowName":"08.交易运营事项用印审批OA流程-苏伟-2024-01-22（附件:数字国联2023年总结）","flowStatusType":"3"}],"status":"SUCCESS"}
     *
     * @param requestId
     * @return
     */
    public List<OaFileDto> getOperateMattersOaFile(String requestId) {
        List<OaFileDto> resList = Lists.newArrayList();

        String retStr = this.getRequestData(requestId);
        logger.info("调用OA查询交易运营事项用印审批OA流程返回:" + retStr);

        JSONObject resultJSONObject = JSONObject.parseObject(retStr);

        if (StrUtil.isEmpty(retStr) || resultJSONObject == null || !GATEWAY_RET_CODE_SUCCESS.equals(resultJSONObject.get("code"))) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单requestId={}，接口返回异常：{}", requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }

        JSONArray dataJson = resultJSONObject.getJSONArray("data");
        JSONObject jsonObject = dataJson.getJSONObject(0);
        JSONObject flowInfosJSONObject = jsonObject.getJSONObject("flowInfos");//表单个性化字段信息

        //股票衍生品客户id
        String derCustId = flowInfosJSONObject.getString("custId");

        //获取用印文件
        JSONArray signetFileList = flowInfosJSONObject.getJSONArray("sealFileFileInfo");
        if (CollectionUtil.isNotEmpty(signetFileList)) {
            for (int i = 0; i < signetFileList.size(); i++) {
                JSONObject fileObject = signetFileList.getJSONObject(i);
                resList.add(OaFileDto.builder().fileName(fileObject.getString("fileName")).custId(derCustId).oaFileId(fileObject.getString("id")).url(fileObject.getString("url")).build());
            }
        }

        //获取不用印的文件
        //signAppendix
        JSONArray fileList = flowInfosJSONObject.getJSONArray("signAppendixFileInfo");
        if (CollectionUtil.isNotEmpty(fileList)) {
            for (int i = 0; i < fileList.size(); i++) {
                JSONObject fileObject = fileList.getJSONObject(i);
                resList.add(OaFileDto.builder().fileName(fileObject.getString("fileName")).custId(derCustId).oaFileId(fileObject.getString("id")).url(fileObject.getString("url")).build());

            }
        }
        return resList;
    }

    /**
     * 根据oa的文件id获取文件留信息
     *
     * @param fileDtos
     * @return
     */
    public List<OaFileDto> getFileStreamByFileId(List<OaFileDto> fileDtos) {
        if (CollectionUtil.isEmpty(fileDtos)) {
            return null;
        }
        for (OaFileDto fileDto : fileDtos) {
            ResponseEntity<byte[]> responseEntity = eurekaOaFlowFeignService.downSingleAppendixFromOANew(fileDto.getOaFileId());
            if (Objects.nonNull(responseEntity)) {
                byte[] bytes = responseEntity.getBody();
                MultipartFile multipartFile = new MockMultipartFile(fileDto.getFileName(), fileDto.getFileName(), ContentType.APPLICATION_OCTET_STREAM.toString(), bytes);
                fileDto.setFile(multipartFile);
            }
        }
        return fileDtos;
    }


    /*
     * 调用OA查询表单数据
     * OA接口正常返回：
     * {"code":0,"data":[{"flowNodeCode":1106974,"flowNode":"结束","requestId":464981,"flowInfos":{"ID":24,"applyNumber":"zgcppslc20210600024","applyDate":"2021-06-10","applicant":"杨昳,yiyang@glsc.com.cn","applicantDepart":"资产管理部/运营管理-运营","applicantComp":"国联证券总部","businessType":"集合标类","productSelect":"1000241","reviewer":"张春蓉","depReviewer":"杨昳","reviewerReply":"发起人意见落实回复","depReviewerReply":"表决已全票“同意”","businessTypeCode":2,"reviewerReplyCode":0,"depReviewerReplyCode":1},"flowStatusType":"3"}],"status":"SUCCESS"}
     * OA接口异常返回数据：
     * {"status":"EXCEPTION","code":17,"msg":"业务异常，查询结果为NULL"}
     * */
    public SynOaDigitalKeyDto getOAFormData4Digital(String workflowId, String requestId) throws NoSuchFieldException, IllegalAccessException {
        String retStr = this.getRequestData(requestId);
        logger.info("调用OA查询表单数据数字证书信息返回:" + retStr);

        JSONObject retJSONObject = JSONObject.parseObject(retStr);

        if (StrUtil.isEmpty(retStr) || retJSONObject == null || !GATEWAY_RET_CODE_SUCCESS.equals(retJSONObject.get("code"))) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }

        //查询OA表单数据字段
        String fieldList = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_DIGITAL_KEY_FIELD);
        SynOaDigitalKeyDto synOaDigitalKeyDto = new SynOaDigitalKeyDto();
        synOaDigitalKeyDto.setWorkflowId(workflowId);
        synOaDigitalKeyDto.setRequestId(requestId);


        JSONArray dataJson = retJSONObject.getJSONArray("data");
        JSONObject jsonObject = dataJson.getJSONObject(0);
        JSONObject flowInfosJSONObject = jsonObject.getJSONObject("flowInfos");//表单个性化字段信息

        //表单公共字段解析
        Integer flowNodeCode = jsonObject.getInteger("flowNodeCode");
        synOaDigitalKeyDto.setFlowNodeCode(flowNodeCode);

        String workflowName = retJSONObject.getString("workflowName");
        if (StrUtil.isNotEmpty(workflowName)) {
            synOaDigitalKeyDto.setWorkflowName(workflowName);
        }
        String flowNode = jsonObject.getString("flowNode");
        if (StrUtil.isNotEmpty(flowNode)) {
            synOaDigitalKeyDto.setFlowNode(StrUtil.trim(flowNode));
        }
        String flowStatusType = jsonObject.getString("flowStatusType");
        if (StrUtil.isNotEmpty(flowStatusType)) {
            synOaDigitalKeyDto.setFlowStatusType(StrUtil.trim(flowStatusType));
        }

        //配置个性化表单解析
        if (StrUtil.isNotEmpty(fieldList)) {
            String[] detailFormList = fieldList.split(",");
            for (String current : detailFormList) {
                if (flowInfosJSONObject.containsKey(current)) {
                    Field name = synOaDigitalKeyDto.getClass().getDeclaredField(current + "");
                    name.setAccessible(true);
                    name.set(synOaDigitalKeyDto, flowInfosJSONObject.getString(current));
                    name.setAccessible(false);
                }
            }
        }

        Integer applyDeptId = flowInfosJSONObject.getInteger("applicantDepartId");
        synOaDigitalKeyDto.setApplyDeptId(applyDeptId);
        String applyDeptName = flowInfosJSONObject.getString("applicantDepart");
        synOaDigitalKeyDto.setApplyDeptName(applyDeptName);
        Integer applyTypeCode = flowInfosJSONObject.getInteger("applyTypeCode");
        synOaDigitalKeyDto.setApplyTypeCode(applyTypeCode);

        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap1");
        List<SynOaDigitalKeyInfoDto> synOaDigitalKeyInfoDtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaDigitalKeyInfoDtoList(detailMap, fieldList, synOaDigitalKeyInfoDtoList);
        }

        detailMap = flowInfosJSONObject.getJSONArray("detailMap2");
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaDigitalKeyInfoDtoList(detailMap, fieldList, synOaDigitalKeyInfoDtoList);
        }

        detailMap = flowInfosJSONObject.getJSONArray("detailMap3");
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaDigitalKeyInfoDtoList(detailMap, fieldList, synOaDigitalKeyInfoDtoList);
        }

        synOaDigitalKeyDto.setDigitalKeyInfoDtoList(synOaDigitalKeyInfoDtoList);

        logger.info("获取OA表单数字证书信息，返回synOaDigitalKeyDto:" + synOaDigitalKeyDto);
        return synOaDigitalKeyDto;
    }

    private void buildSynOaDigitalKeyInfoDtoList(JSONArray detailMap, String fieldList, List<SynOaDigitalKeyInfoDto> synOaTradeSeatInfoDtoList) throws NoSuchFieldException, IllegalAccessException {
        for (int i = 0; i < detailMap.size(); i++) {
            JSONObject object = detailMap.getJSONObject(i);
            SynOaDigitalKeyInfoDto synOaDigitalKeyInfoDto = new SynOaDigitalKeyInfoDto();
            //配置个性化表单解析
            if (StrUtil.isNotEmpty(fieldList)) {
                String[] detailFormList = fieldList.split(",");
                for (String current : detailFormList) {
                    if (object.containsKey(current)) {
                        Field name = synOaDigitalKeyInfoDto.getClass().getDeclaredField(current + "");
                        name.setAccessible(true);
                        name.set(synOaDigitalKeyInfoDto, object.getString(current));
                        name.setAccessible(false);
                    }
                }
            }
            String useDepartment = object.getString("useDepartment");
            synOaDigitalKeyInfoDto.setUseDepartment(useDepartment);
            String custodianAccount = object.getString("custodianAccount");
            synOaDigitalKeyInfoDto.setCustodianAccount(custodianAccount);
            synOaTradeSeatInfoDtoList.add(synOaDigitalKeyInfoDto);
        }
    }

    /**
     * 调用网关批量上传附件接口
     * 接口正常返回：
     * {"code":0,"data":[{"flowNodeCode":1106974,"flowNode":"结束","requestId":464981,"flowInfos":{"ID":24,"applyNumber":"zgcppslc20210600024","applyDate":"2021-06-10","applicant":"杨昳,yiyang@glsc.com.cn","applicantDepart":"资产管理部/运营管理-运营","applicantComp":"国联证券总部","businessType":"集合标类","productSelect":"1000241","reviewer":"张春蓉","depReviewer":"杨昳","reviewerReply":"发起人意见落实回复","depReviewerReply":"表决已全票“同意”","businessTypeCode":2,"reviewerReplyCode":0,"depReviewerReplyCode":1},"flowStatusType":"3"}],"status":"SUCCESS"}
     * 接口异常返回数据：
     * {"status":"EXCEPTION","code":17,"msg":"业务异常，查询结果为NULL"}
     */
    public String uploadDoc(MultipartFile[] file) {
        for (MultipartFile f : file) {
            logger.info(f.getOriginalFilename());
        }
        String message = eurekaOaFlowFeignService.uploadDoc(file);
        return message;
    }

    /**
     * 调用网关批量文件上传接口返回报文解析生成List
     *
     * @param ret
     * @return
     */
    private List<OaBatchUploadFileDto> buildOaBatchUploadFileList(String ret) {
        JSONObject jsonObject = JSONObject.parseObject(ret);
        String data = jsonObject.getString("data");
        List<OaBatchUploadFileDto> oaBatchUploadFileList = JSON.parseArray(data, OaBatchUploadFileDto.class);
        return oaBatchUploadFileList;
    }


    /**
     * 上传文件到oa
     *
     * @param
     * @return
     */
    public OaBatchUploadFileDto uploadOaFileAndReturnPath(File file) {
        if (Objects.nonNull(file)) {
            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(file);
                MultipartFile[] multipartFiles = new MultipartFile[1];
                multipartFiles[0] = new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);

                String uploadFileResponse = uploadDoc(multipartFiles);
                List<OaBatchUploadFileDto> oaBatchUploadFileList = buildOaBatchUploadFileList(uploadFileResponse);
                return CollectionUtil.isNotEmpty(oaBatchUploadFileList) ? oaBatchUploadFileList.get(0) : null;
            } catch (Exception e) {
                logger.error("创建外部系统权限oa流程的上传附件发生异常", e);
            }
        }
        return null;
    }


    /**
     * 本地文件转为MultipartFile类型(文件路径)
     *
     * @param filePath
     * @return
     */
    private static MultipartFile getMultipartFile(String filePath) {
        FileItem fileItem = createFileItem(filePath);
        return new CommonsMultipartFile(fileItem);
    }

    private static FileItem createFileItem(String filePath) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        File file = new File(filePath);
        FileItem item = factory.createItem("file", "text/plain", true,
                file.getName());

        long fileSize = file.length();
        int bytesRead = 0;
        byte[] buffer = new byte[(int) fileSize];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, buffer.length)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            logger.error("异常", e);
        }
        return item;
    }

    private JSONArray converToJsonArray(String res) {
        if (res.isEmpty()) {
            throw GatewayException.error("查询结果为空");
        }
        JSONObject jsonObject = JSONObject.parseObject(res);
        return jsonObject.getJSONArray("data");
    }


    /**
     * 邮件发送
     *
     * @param mailTitle
     * @param mailContent
     * @param mailRecvList
     */
    private void sendDocCollectionRemindEmail(String mailTitle, String mailContent, List<String> mailRecvList) {
        //邮件发送
        if (CollectionUtils.isEmpty(mailRecvList)) {
            logger.warn("OA流程工作流档案催收提醒未查找到相关提醒人");
            mailService.sendMailToAdmin(mailTitle, mailContent);
            mailService.sendMailToAdmin(mailTitle + "OA流程工作流档案催收提醒未查找到相关提醒人", "OA流程工作流档案催收提醒未查找到相关提醒人");
        } else {
            mailRecvList = mailRecvList.stream().distinct().collect(Collectors.toList());
            mailService.sendMail(mailRecvList.toArray(new String[mailRecvList.size()]), null, mailTitle, mailContent, null);
        }
    }

    public TradeAccountHistory getOATradeAccount(String workflowId, String requestId) {
        String retStr = this.getRequestData(requestId);
        logger.info("调用OA查询表单数据账户信息返回:" + retStr);

        JSONObject retJSONObject = JSONObject.parseObject(retStr);

        if (StrUtil.isEmpty(retStr) || retJSONObject == null || !GATEWAY_RET_CODE_SUCCESS.equals(retJSONObject.get("code"))) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }

        //查询OA表单数据字段
//        String fieldList = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_TRADE_SEAT_FIELD);
        TradeAccountHistory tradeAccountHistory = new TradeAccountHistory();
        tradeAccountHistory.setWorkflowId(workflowId);
        tradeAccountHistory.setRequestId(requestId);


        JSONArray dataJson = retJSONObject.getJSONArray("data");
        JSONObject jsonObject = dataJson.getJSONObject(0);
        JSONObject flowInfosJSONObject = jsonObject.getJSONObject("flowInfos");//表单个性化字段信息

        //表单公共字段解析
        Integer flowNodeCode = jsonObject.getInteger("flowNodeCode");
        tradeAccountHistory.setFlowNodeCode(flowNodeCode);

        String workflowName = retJSONObject.getString("workflowName");
        if (StrUtil.isNotEmpty(workflowName)) {
            tradeAccountHistory.setWorkflowName(workflowName);
        }
        String flowNode = jsonObject.getString("flowNode");
        if (StrUtil.isNotEmpty(flowNode)) {
            tradeAccountHistory.setFlowNode(StrUtil.trim(flowNode));
        }
        String flowStatusType = jsonObject.getString("flowStatusType");
        if (StrUtil.isNotEmpty(flowStatusType)) {
            tradeAccountHistory.setFlowStatusType(StrUtil.trim(flowStatusType));
        }

//        //配置个性化表单解析
//        if (StrUtil.isNotEmpty(fieldList)) {
//            String[] detailFormList = fieldList.split(",");
//            for (String current : detailFormList) {
//                if (flowInfosJSONObject.containsKey(current)) {
//                    Field name = tradeAccountHistory.getClass().getDeclaredField(current + "");
//                    name.setAccessible(true);
//                    name.set(tradeAccountHistory, flowInfosJSONObject.getString(current));
//                    name.setAccessible(false);
//                }
//            }
//        }

        String accountSetupOrgCode = flowInfosJSONObject.getString("accountSetupOrgCode");
        tradeAccountHistory.setAccountSetupOrgCode(accountSetupOrgCode);

        String applicantDepart = flowInfosJSONObject.getString("applicantDepart");
        tradeAccountHistory.setApplicantDepart(applicantDepart);

        String applicantDepartId = flowInfosJSONObject.getString("applicantDepartId");
        tradeAccountHistory.setApplicantDepartId(applicantDepartId);

        String applicantCompId = flowInfosJSONObject.getString("applicantCompId");
        tradeAccountHistory.setApplicantCompId(applicantCompId);

        String accountType = flowInfosJSONObject.getString("accountType");
        tradeAccountHistory.setAccountType(accountType);

        String accountTypeCode = flowInfosJSONObject.getString("accountTypeCode");
        tradeAccountHistory.setAccountTypeCode(accountTypeCode);

        String accountSetupOrg = flowInfosJSONObject.getString("accountSetupOrg");
        tradeAccountHistory.setAccountSetupOrg(accountSetupOrg);

        String applicant = flowInfosJSONObject.getString("applicant");
        tradeAccountHistory.setApplicant(applicant);

        String businessType = flowInfosJSONObject.getString("businesstype");
        tradeAccountHistory.setBusinessType(businessType);

        String applicantComp = flowInfosJSONObject.getString("applicantComp");
        tradeAccountHistory.setApplicantComp(applicantComp);

        String applyExplain = flowInfosJSONObject.getString("applyExplain");
        tradeAccountHistory.setApplyExplain(applyExplain);

        String businessTypeCode = flowInfosJSONObject.getString("businesstypeCode");
        tradeAccountHistory.setBusinessTypeCode(businessTypeCode);

        String applicantAccount = flowInfosJSONObject.getString("applicantAccount");
        tradeAccountHistory.setApplicantAccount(applicantAccount);

        String applyDate = flowInfosJSONObject.getString("applyDate");
        tradeAccountHistory.setApplyDate(applyDate);

        String applyNumber = flowInfosJSONObject.getString("applyNumber");
        tradeAccountHistory.setApplyNumber(applyNumber);

        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap1");
        List<TradeAccountShareHolder> tradeAccountShareHolders = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(detailMap)) {
            buildSynOaTradeAccountListShareHolder(detailMap, tradeAccountShareHolders, requestId);
        }
        tradeAccountHistory.setShareHolderListString(JSONObject.toJSONString(tradeAccountShareHolders));
        tradeAccountHistory.setShareHolderList(tradeAccountShareHolders);

        JSONArray ownFundMap = flowInfosJSONObject.getJSONArray("detailMap2");
        List<TradeAccountOwnFund> tradeAccountOwnFunds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(ownFundMap)) {
            buildSynOaTradeAccountListOwnFund(ownFundMap, tradeAccountOwnFunds, requestId);
        }
        tradeAccountHistory.setOwnFundListString(JSONObject.toJSONString(tradeAccountOwnFunds));
        tradeAccountHistory.setOwnFundList(tradeAccountOwnFunds);

        JSONArray saleFundMap = flowInfosJSONObject.getJSONArray("detailMap3");
        List<TradeAccountSaleFund> tradeAccountSaleFunds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(saleFundMap)) {
            buildSynOaTradeAccountListSaleFund(saleFundMap, tradeAccountSaleFunds, requestId);
        }
        tradeAccountHistory.setSaleFundListString(JSONObject.toJSONString(tradeAccountSaleFunds));
        tradeAccountHistory.setSaleFundList(tradeAccountSaleFunds);

        JSONArray futureMap = flowInfosJSONObject.getJSONArray("detailMap4");
        List<TradeAccountFurture> tradeAccountFurtures = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(futureMap)) {
            buildSynOaTradeAccountListFurture(futureMap, tradeAccountFurtures, requestId);
        }
        tradeAccountHistory.setFurtureListString(JSONObject.toJSONString(tradeAccountFurtures));
        tradeAccountHistory.setFurtureList(tradeAccountFurtures);

        logger.info("获取OA表单交易单元信息，返回synOaTradeSeatDto:" + tradeAccountHistory);
        return tradeAccountHistory;
    }

    private void buildSynOaTradeAccountListFurture(JSONArray detailMap, List<TradeAccountFurture> tradeAccountFurtures, String requestId) {
        for (int i = 0; i < detailMap.size(); i++) {
            JSONObject object = detailMap.getJSONObject(i);
            TradeAccountFurture tradeAccountFurture = new TradeAccountFurture();

            String teamName = object.getString("teamName");
            tradeAccountFurture.setTeamName(teamName);

            String settlementAccountSelectName = object.getString("settlementAccountSelectName");
            tradeAccountFurture.setSettlementAccountSelectName(settlementAccountSelectName);

            String openAccountDate = object.getString("openAccountDate");
            tradeAccountFurture.setOpenAccountDate(openAccountDate);

            String futureType = object.getString("futureType");
            tradeAccountFurture.setFutureType(futureType);

            String futureUseDepartment = object.getString("futureUseDepartment");
            tradeAccountFurture.setFutureUseDepartment(futureUseDepartment);

            if (object.get("futureUseDepartmentId") != null) {
                Integer futureUseDepartmentId = object.getInteger("futureUseDepartmentId");
                tradeAccountFurture.setFutureUseDepartmentId(futureUseDepartmentId);
            }

            String futureCompanyMoneyAccount = object.getString("futureCompanyMoneyAccount");
            tradeAccountFurture.setFutureCompanyMoneyAccount(futureCompanyMoneyAccount);

            String tradeCode = object.getString("tradeCode");
            tradeAccountFurture.setTradeCode(tradeCode.trim());

            String futureTypeSelectName = object.getString("futureTypeSelectName");
            tradeAccountFurture.setFutureTypeSelectName(futureTypeSelectName);

            String futureCompany = object.getString("futureCompany");
            tradeAccountFurture.setFutureCompany(futureCompany);

            String settlementAccount = object.getString("settlementAccount");
            tradeAccountFurture.setSettlementAccount(settlementAccount);

            String teamNameSelectName = object.getString("teamNameSelectName");
            tradeAccountFurture.setTeamNameSelectName(teamNameSelectName);

            String openDate = object.getString("openDate");
            tradeAccountFurture.setOpenDate(openDate);

            tradeAccountFurture.setRequestId(requestId);

            tradeAccountFurtures.add(tradeAccountFurture);
        }
    }

    private void buildSynOaTradeAccountListSaleFund(JSONArray detailMap, List<TradeAccountSaleFund> tradeAccountSaleFunds, String requestId) {
        for (int i = 0; i < detailMap.size(); i++) {
            JSONObject object = detailMap.getJSONObject(i);
            TradeAccountSaleFund tradeAccountSaleFund = new TradeAccountSaleFund();

            String relateInfo = object.getString("relateInfo");
            tradeAccountSaleFund.setRelateInfo(relateInfo);

            String saleFundRelateBank = object.getString("saleFundRelateBank");
            tradeAccountSaleFund.setSaleFundRelateBank(saleFundRelateBank);

            String platName = object.getString("platName");
            tradeAccountSaleFund.setPlatName(platName);

            String admin = object.getString("admin");
            tradeAccountSaleFund.setAdmin(admin);

            String adminId = object.getString("adminId");
            tradeAccountSaleFund.setAdminId(adminId);

            String adminAccount = object.getString("adminAccount");
            tradeAccountSaleFund.setAdminAccount(adminAccount);

            String accountUseInfo = object.getString("accountUseInfo");
            tradeAccountSaleFund.setAccountUseInfo(accountUseInfo);

            String saleFundRelateBankSelectName = object.getString("saleFundRelateBankSelectName");
            tradeAccountSaleFund.setSaleFundRelateBankSelectName(saleFundRelateBankSelectName);

            String account = object.getString("account");
            if (StringUtils.isNotBlank(account)) {
                tradeAccountSaleFund.setAccount(account.trim());
            }

            String operator = object.getString("operator");
            tradeAccountSaleFund.setOperator(operator);

            String operatorId = object.getString("operatorId");
            tradeAccountSaleFund.setOperatorId(operatorId);

            String operatorAccount = object.getString("operatorAccount");
            tradeAccountSaleFund.setOperatorAccount(operatorAccount);

            String saleFundphone = object.getString("saleFundphone");
            tradeAccountSaleFund.setSaleFundPhone(saleFundphone);

            String openDate = object.getString("openDate1");
            tradeAccountSaleFund.setOpenDate(openDate);

            tradeAccountSaleFund.setRequestId(requestId);

            tradeAccountSaleFunds.add(tradeAccountSaleFund);
        }
    }

    private void buildSynOaTradeAccountListOwnFund(JSONArray detailMap, List<TradeAccountOwnFund> tradeAccountOwnFunds, String requestId) {
        for (int i = 0; i < detailMap.size(); i++) {
            JSONObject object = detailMap.getJSONObject(i);
            TradeAccountOwnFund tradeAccountOwnFund = new TradeAccountOwnFund();
//            //配置个性化表单解析
//            if (StrUtil.isNotEmpty(fieldList)) {
//                String[] detailFormList = fieldList.split(",");
//                for (String current : detailFormList) {
//                    if (object.containsKey(current)) {
//                        Field name = tradeAccountOwnFund.getClass().getDeclaredField(current + "");
//                        name.setAccessible(true);
//                        name.set(tradeAccountOwnFund, object.getString(current));
//                        name.setAccessible(false);
//                    }
//                }
//            }
            String ownFundRelateBank = object.getString("ownFundRelateBank");
            tradeAccountOwnFund.setOwnFundRelateBank(ownFundRelateBank);

            String fundAccount = object.getString("fundAccount");
            tradeAccountOwnFund.setFundAccount(fundAccount.trim());

            String stampInfo = object.getString("stampInfo");
            tradeAccountOwnFund.setStampInfo(stampInfo);

            String ownFundRelateBankSelectName = object.getString("ownFundRelateBankSelectName");
            tradeAccountOwnFund.setOwnFundRelateBankSelectName(ownFundRelateBankSelectName);

            String ownFundphone = object.getString("ownFundphone");
            tradeAccountOwnFund.setOwnFundPhone(ownFundphone);

            String operatorInfo = object.getString("operatorInfo");
            tradeAccountOwnFund.setOperatorInfo(operatorInfo);

            String operatorInfoId = object.getString("operatorInfoId");
            tradeAccountOwnFund.setOperatorInfoId(operatorInfoId);

            String operatorInfoAccount = object.getString("operatorInfoAccount");
            tradeAccountOwnFund.setOperatorInfoAccount(operatorInfoAccount);

            String fundCompany = object.getString("fundCompany");
            tradeAccountOwnFund.setFundCompany(fundCompany);

            String plugInfo = object.getString("plugInfo");
            tradeAccountOwnFund.setPlugInfo(plugInfo);

            String stampInfoSelectName = object.getString("stampInfoSelectName");
            tradeAccountOwnFund.setStampInfoSelectName(stampInfoSelectName);

            String openDate = object.getString("openDate");
            tradeAccountOwnFund.setOpenDate(openDate);

            tradeAccountOwnFund.setRequestId(requestId);

            tradeAccountOwnFunds.add(tradeAccountOwnFund);
        }
    }

    private void buildSynOaTradeAccountListShareHolder(JSONArray detailMap, List<TradeAccountShareHolder> tradeAccountShareHolders, String requestId) {
        for (int i = 0; i < detailMap.size(); i++) {
            JSONObject object = detailMap.getJSONObject(i);
            TradeAccountShareHolder tradeAccountShareHolder = new TradeAccountShareHolder();
//            //配置个性化表单解析
//            if (StrUtil.isNotEmpty(fieldList)) {
//                String[] detailFormList = fieldList.split(",");
//                for (String current : detailFormList) {
//                    if (object.containsKey(current)) {
//                        Field name = tradeAccountShareHolder.getClass().getDeclaredField(current + "");
//                        name.setAccessible(true);
//                        name.set(tradeAccountShareHolder, object.getString(current));
//                        name.setAccessible(false);
//                    }
//                }
//            }
            String market = object.getString("market");
            tradeAccountShareHolder.setMarket(market);

            String shareHolderAccount = object.getString("shareHolderAccount");
            tradeAccountShareHolder.setShareHolderAccount(shareHolderAccount.trim());

            String shareHolderUseDepartment = object.getString("shareHolderUseDepartment");
            tradeAccountShareHolder.setShareHolderUseDepartment(shareHolderUseDepartment);

            if (object.get("shareHolderUseDepartmentId") != null) {
                Integer shareHolderUseDepartmentId = object.getInteger("shareHolderUseDepartmentId");
                tradeAccountShareHolder.setShareHolderUseDepartmentId(shareHolderUseDepartmentId);
            }

            String fundIndex = object.getString("fundIndex");
            tradeAccountShareHolder.setFundIndex(fundIndex);

            String shareHolderAccountName = object.getString("shareHolderAccountName");
            tradeAccountShareHolder.setShareHolderAccountName(shareHolderAccountName);

            String statusSelectName = object.getString("statusSelectName");
            tradeAccountShareHolder.setStatusSelectName(statusSelectName);

            if (object.get("tradUnit") != null) {
                Integer tradUnit = object.getInteger("tradUnit");
                tradeAccountShareHolder.setTradUnit(tradUnit);
                tradeAccountShareHolder.setTradUnitNum(tradeAccountService.getDictJYDYH(tradUnit));
            }

            String marketSelectName = object.getString("marketSelectName");
            tradeAccountShareHolder.setMarketSelectName(marketSelectName);

            String openDate = object.getString("openDate");
            tradeAccountShareHolder.setOpenDate(openDate);

            String fundName = object.getString("fundName");
            tradeAccountShareHolder.setFundName(fundName);

            String remark1 = object.getString("remark1");
            tradeAccountShareHolder.setRemark1(remark1);

            String status = object.getString("status");
            tradeAccountShareHolder.setStatus(status);

            tradeAccountShareHolder.setRequestId(requestId);

            tradeAccountShareHolders.add(tradeAccountShareHolder);
        }
    }

    //    @Transactional
    public void syncOaXinYiFormData4XinYi(String workflowId, String requestId) {
        List<WorkflowRequestbaseDto> requestDataNew = this.getRequestDataNew(requestId);
        if (CollectionUtils.isEmpty(requestDataNew) || StringUtils.isEmpty(requestDataNew.get(0).getStatus())
        ) {
//                || !requestDataNew.get(0).getStatus().equals("运营管理部资金岗")) {
            String errMsg = MessageFormat.format("该流程节点状态不正确，跳过调用新意workflowId={0}-requestId={1}，流程节点状态：{2}", workflowId, requestId, requestDataNew.get(0).getStatus());
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }

        XinYiLog yiLog = new XinYiLog().setStatus("Y").setRequestId(requestId).setWorkflowId(workflowId);
        List<XinYiLog> successLog = xinYiLogRepo.findAll(Example.of(yiLog));
        if (CollectionUtil.isNotEmpty(successLog)) {
            String errMsg = MessageFormat.format("已存在创建成功的新意指令,不在创建workflowId={0}-requestId={1}", workflowId, requestId);
            logger.error(errMsg);
            //throw GatewayException.error(errMsg);
            return;
        }

        String retStr = this.getRequestDataOrigin(requestId, workflowId);
        logger.info("创建新意指令调用OA查询表单数据返回:" + retStr);
        // 155603
        String syncGuShouYiJiConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_GUSHOU_YIJI_WORKFLOW_ID);
        // 336104
        String syncGuShouConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_GUSHOU_WORKFLOW_ID);
        // 336103
        String syncGuYanConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_GUYAN_WORKFLOW_ID);
        // 336113
        String syncZiYouConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_ZIYOU_WORKFLOW_ID);
        // 251103
        String syncYunYingConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_YUNYING_WORKFLOW_ID);
        // 336116
        String syncZhuanYongConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_ZHUANYONG_WORKFLOW_ID);
        // 336105
        String syncGuShouZhaiQuanConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_GUSHOU_ZHAIQUAN_WORKFLOW_ID);
        // 336114
        String syncJiJinConfigValue = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_JIJIN_WORKFLOW_ID);

        JSONObject retJSONObject = JSONObject.parseObject(retStr);
        if (StrUtil.isEmpty(retStr) || retJSONObject == null || !GATEWAY_RET_CODE_SUCCESS.equals(retJSONObject.get("code"))) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }

        String paramJson = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_FIELD);
        XinYiParamDto paramDto = JSONObject.parseObject(paramJson, XinYiParamDto.class);
        //查询OA表单数据字段
        JSONArray dataJson = retJSONObject.getJSONArray("data");
        if (CollectionUtils.isEmpty(dataJson)) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        JSONObject jsonObject = dataJson.getJSONObject(0);
        JSONObject flowInfosJSONObject = jsonObject.getJSONObject("flowInfos");//表单个性化字段信息
        String oaName = jsonObject.getString("workflowName");

        if (workflowId.equals(syncGuShouYiJiConfigValue)) {
            callGuShouYiJi(workflowId, requestId, paramDto, flowInfosJSONObject, oaName);
        }
        if (workflowId.equals(syncGuShouConfigValue)) {
            callGuShou(workflowId, requestId, retStr, paramDto, flowInfosJSONObject, oaName);
        }
        if (workflowId.equals(syncGuYanConfigValue)) {
            callGuYan(workflowId, requestId, retStr, paramDto, flowInfosJSONObject, oaName);
        }
        if (workflowId.equals(syncZiYouConfigValue)) {
            callZiYou(workflowId, requestId, retStr, paramDto, flowInfosJSONObject, oaName);
        }
        if (workflowId.equals(syncYunYingConfigValue)) {
            callYunYing(workflowId, requestId, paramDto, flowInfosJSONObject, oaName);
        }
        if (workflowId.equals(syncZhuanYongConfigValue)) {
            callZhuanYong(workflowId, requestId, retStr, paramDto, flowInfosJSONObject, oaName);
        }
        if (workflowId.equals(syncGuShouZhaiQuanConfigValue)) {
            callGuShouZhaiQuan(workflowId, requestId, retStr, paramDto, flowInfosJSONObject, oaName);
        }
        if (workflowId.equals(syncJiJinConfigValue)) {
            callJiJin(workflowId, requestId, retStr, paramDto, flowInfosJSONObject, oaName);
        }
    }

    private void callJiJin(String workflowId, String requestId, String retStr, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap1");
        if (CollectionUtils.isEmpty(detailMap)) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        detailMap.forEach(obj -> {
            JSONObject jsonObj = (JSONObject) obj;
            // 收款信息
            String sqtbje = jsonObj.getString("SQDBJE");//金额
            String skzhzj = jsonObj.getString("SKZH");//账号
            Skzh skzh = null;
            if (StringUtils.isBlank(skzhzj)) {
                skzhzj = jsonObj.getString("SKZH2");//账号
                skzh = skzhRepo.findByYhzh(skzhzj);
            } else {
                skzh = skzhRepo.findByYhzhzj(skzhzj);
            }
            if (skzh == null || skzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String skdezfh = jsonObj.getString("SKDEZFH");//大额账号
            if (StringUtils.isBlank(skdezfh)) {
                skdezfh = jsonObj.getString("SKFDEZFHH2");//大额账号
            }
            String ykrq = jsonObj.getString("YKRQ");
            String bz = jsonObj.getString("HKBZ");
            // 付款信息
            String fkzhzj = jsonObj.getString("FKZH"); // 账户
            Fkzh fkzh = fkzhRepo.findByYhzhzj(fkzhzj);
            if (fkzh == null || fkzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String yhzhh = jsonObj.getString("FKDEZFH");
            String date = DateUtils.reFormatDate(ykrq, DateUtils.formatDate_, DateUtils.formatDate);

            paramDto
                    .buildRecInfo(skzh.getYhzhmc(), skzh.getYhzh(), skzh.getKhyh(), "9999")
                    .buildPayInfo(fkzh.getYhzhmc(), fkzh.getYhzh(), fkzh.getKhyh(), "9999")
                    .buildDateInfo(date, date, date)
                    .setOccurAmt(sqtbje).setNote(bz)
                    .setPayBigBankAcc(yhzhh)
                    .setRecBigBankAcc(skdezfh);
            callXinYi(workflowId, requestId, paramDto, jsonObj.getString("ID"), oaName, jsonObj.getString("HBTJ"), "基金申赎流程");
        });
    }

    private void callGuShouZhaiQuan(String workflowId, String requestId, String retStr, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap3");
        if (CollectionUtils.isEmpty(detailMap)) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        detailMap.forEach(obj -> {
            JSONObject jsonObj = (JSONObject) obj;
            // 收款信息
            String sqtbje = jsonObj.getString("SQTBJE");//金额
            String skzhzj = jsonObj.getString("SKZH");
            Skzh skzh = null;
            if (StringUtils.isBlank(skzhzj)) {
                skzhzj = jsonObj.getString("SKZH2");//账号
                skzh = skzhRepo.findByYhzh(skzhzj);
            } else {
                skzh = skzhRepo.findByYhzhzj(skzhzj);
            }
            if (skzh == null || skzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String skdezfh = jsonObj.getString("SKDEZFH");//大额账号
            if (StringUtils.isBlank(skdezfh)) {
                skdezfh = jsonObj.getString("SKFDEZFHH2");//大额账号
            }

            String ykrq = jsonObj.getString("YKRQ");
            String bz = jsonObj.getString("BZ");
            // 付款信息
            String fkzhzj = jsonObj.getString("FKZH"); // 账户
            Fkzh fkzh = fkzhRepo.findByYhzhzj(fkzhzj);
            if (fkzh == null || fkzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String yhzhh = jsonObj.getString("FKDEZFH");
            String date = DateUtils.reFormatDate(ykrq, DateUtils.formatDate_, DateUtils.formatDate);

            paramDto
                    .buildRecInfo(skzh.getYhzhmc(), skzh.getYhzh(), skzh.getKhyh(), "9999")
                    .buildPayInfo(fkzh.getYhzhmc(), fkzh.getYhzh(), fkzh.getKhyh(), "9999")
                    .buildDateInfo(date, date, date)
                    .setOccurAmt(sqtbje).setNote(bz)
                    .setPayBigBankAcc(yhzhh)
                    .setRecBigBankAcc(skdezfh);
            callXinYi(workflowId, requestId, paramDto, jsonObj.getString("ID"), oaName, jsonObj.getString("HBTJ"), "固定收益部非债券交易审核划款流程");
        });
    }

    private void callZhuanYong(String workflowId, String requestId, String retStr, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap");
        if (CollectionUtils.isEmpty(detailMap)) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        detailMap.forEach(obj -> {
            JSONObject jsonObj = (JSONObject) obj;
            // 收款信息
            String sqtbje = jsonObj.getString("ZJJE");//金额
            String zhmsk = jsonObj.getString("SKZHMC");// 账户名
            String khhsk = jsonObj.getString("SKZHKHYH");// 开户行
            String skzhzj = jsonObj.getString("SKZH");//账号 TODO
            Skzh skzh = skzhRepo.findByYhzhzj(skzhzj);
            if (skzh == null || skzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String skdezfh = jsonObj.getString("SKDEZFH");//大额账号
            String ykrq = jsonObj.getString("YKRQ");
            String bz = jsonObj.getString("BZ");
            // 付款信息
            String fkzhzj = jsonObj.getString("FKZH"); // 账户
            Fkzh fkzh = fkzhRepo.findByYhzhzj(fkzhzj);
            if (fkzh == null || fkzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String khh = jsonObj.getString("FKZHKHYH");
            String fkzhmc = jsonObj.getString("FKZHMC");// 账户名
            String yhzhh = jsonObj.getString("FKDEZFH");
            String date = DateUtils.reFormatDate(ykrq, DateUtils.formatDate_, DateUtils.formatDate);

            paramDto.buildRecInfo(zhmsk, skzh.getYhzh(), khhsk, "9999")
                    .buildPayInfo(fkzhmc, fkzh.getYhzh(), khh, "9999")
                    .buildDateInfo(date, date, date)
                    .setOccurAmt(sqtbje).setNote(bz)
                    .setPayBigBankAcc(yhzhh)
                    .setRecBigBankAcc(skdezfh);
            callXinYi(workflowId, requestId, paramDto, jsonObj.getString("ID"), oaName, jsonObj.getString("HBTJ"), "公司专用资金使用划付申请流程");
        });
    }

    private void callYunYing(String workflowId, String requestId, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        String sqtbje = flowInfosJSONObject.getString("SQJE");//金额
        String ykrq = flowInfosJSONObject.getString("SQRQ");
        String bz = flowInfosJSONObject.getString("HKSM");

        //备注:国联证券拆借还款，资金账户户名:江西永丰农村商业银行股份有限公司，资金开户行:中央结算公司，资金账号:000000408282001，支付系统行号:901000115

        String[] split = bz.split("，");

        // 付款信息
        String skyhzh = flowInfosJSONObject.getString("SKYHZH"); // 账户
        String skyhmc = flowInfosJSONObject.getString("SKYHMC");
        String skr = flowInfosJSONObject.getString("SKR");// 账户名

        for (String item : split) {
            if (item.contains("资金账户户名")) {
                skr = item.replaceAll("资金账户户名：", "");
            }
            if (item.contains("资金开户行")) {
                skyhmc = item.replaceAll("资金开户行：", "");
            }
            if (item.contains("资金账号")) {
                skyhzh = item.replaceAll("资金账号：", "");
            }
        }

        String date = DateUtils.reFormatDate(ykrq, DateUtils.formatDate_, DateUtils.formatDate);

        paramDto.buildRecInfo(skr, skyhzh, skyhmc, "9999")
                .buildDateInfo(date, date, date)
                .setOccurAmt(sqtbje).setNote(bz);
        callXinYi(workflowId, requestId, paramDto, null, oaName, null, "资金运营部自有资金划付流程");
    }

    private void callZiYou(String workflowId, String requestId, String retStr, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap");
        if (CollectionUtils.isEmpty(detailMap)) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        detailMap.forEach(obj -> {
            JSONObject jsonObj = (JSONObject) obj;
            // 收款信息
            String sqtbje = jsonObj.getString("ZJJE");//金额
            String skzhzj = jsonObj.getString("SKZH");//账号
            Skzh skzh = skzhRepo.findByYhzhzj(skzhzj);
            if (skzh == null || skzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String skdezfh = jsonObj.getString("SKDEZFH");//大额账号

            String ykrq = jsonObj.getString("YKRQ");
            String bz = jsonObj.getString("BZ");
            // 付款信息
            String fkzhzj = jsonObj.getString("FKZH"); // 账户
            Fkzh fkzh = fkzhRepo.findByYhzhzj(fkzhzj);
            if (fkzh == null || fkzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            String yhzhh = jsonObj.getString("FKDEZFH");
            String date = DateUtils.reFormatDate(ykrq, DateUtils.formatDate_, DateUtils.formatDate);

            paramDto
                    .buildRecInfo(skzh.getYhzhmc(), skzh.getYhzh(), skzh.getKhyh(), "9999")
                    .buildPayInfo(fkzh.getYhzhmc(), fkzh.getYhzh(), fkzh.getKhyh(), "9999")
                    .buildDateInfo(date, date, date)
                    .setOccurAmt(sqtbje).setNote(bz)
                    .setPayBigBankAcc(yhzhh)
                    .setRecBigBankAcc(skdezfh);
            callXinYi(workflowId, requestId, paramDto, jsonObj.getString("ID"), oaName, jsonObj.getString("HBTJ"), "自有结算资金划付申请流程");
        });
    }

    private void callGuYan(String workflowId, String requestId, String retStr, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        JSONArray detailMap = flowInfosJSONObject.getJSONArray("detailMap");
        if (CollectionUtils.isEmpty(detailMap)) {
            String errMsg = MessageFormat.format("创建新意指令,调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        logger.info("创建新意指令,=======0=======workflowId={}-requestId={}-oa流程中的detailMap={}", workflowId, requestId, JSON.toJSONString(detailMap));
        Set<String> fkzhzjSet = new HashSet<>();
        for (Object obj : detailMap) {
            JSONObject jsonObj = (JSONObject) obj;
            fkzhzjSet.add(jsonObj.getString("FKZH"));
        }
        logger.error("创建新意指令,付款账户信息查询参数为{}", JSON.toJSONString(fkzhzjSet));
        List<Fkzh> fkzhzjList = findByFkzhzjList(fkzhzjSet);
        if (CollectionUtil.isEmpty(fkzhzjList)) {
            logger.error("创建新意指令失败,未查询到付款账户信息,付款账户信息查询参数为{}", JSON.toJSONString(fkzhzjSet));
            return;
        }
        Map<String, Fkzh> fkzhMap = fkzhzjList.stream().collect(Collectors.toMap(Fkzh::getYhzhzj, e -> e, (i, j) -> j));
        logger.info("创建新意指令,付款账户信息为{}", JSON.toJSONString(fkzhzjList));

        for (Object obj : detailMap) {
            try {
                dealOneGuYanOrder(obj, workflowId, requestId, paramDto, fkzhMap, oaName);
            } catch (Exception e) {
                logger.error("创建新意指令,触发新意指令异常", e);
            }

        }
    }

    //@Transactional
    public void dealOneGuYanOrder(Object obj, String workflowId, String requestId, XinYiParamDto dto, Map<String, Fkzh> fkzhMap, String oaName) {
        XinYiParamDto paramDto = XinYiParamDto.builder().build();
        BeanUtils.copyProperties(dto, paramDto);

        JSONObject jsonObj = (JSONObject) obj;
        // 收款信息
        String sqtbje = jsonObj.getString("SQTBJE");//金额
        String yhzh = jsonObj.getString("SKZH2");//账号
        Skzh skzh = null;
        if (StringUtils.isBlank(yhzh)) {
            yhzh = jsonObj.getString("SKZH");
            skzh = skzhRepo.findByYhzhzj(yhzh);
        } else {
            skzh = skzhRepo.findByYhzh(yhzh);
        }
        if (skzh == null || skzh.getYhzh() == null) {
            String errMsg = MessageFormat.format("创建新意指令,不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, yhzh);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        String skdezfh = jsonObj.getString("SKDEZFH");//大额账号
        String ykrq = jsonObj.getString("YKRQ");
        String bz = jsonObj.getString("HKBZ");
        // 付款信息
        String fkzhzj = jsonObj.getString("FKZH"); // 账户
        Fkzh fkzh = fkzhMap.get(fkzhzj);

        logger.info("创建新意指令,=======1=======workflowId={}-requestId={}-fkzhzj={}的付款方账号信息{}", workflowId, requestId, fkzhzj, JSON.toJSONString(fkzh));
        if (fkzh == null || fkzh.getYhzh() == null) {
            String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, fkzhzj);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        String yhzhh = jsonObj.getString("YHZHH");
        String date = DateUtils.reFormatDate(ykrq, DateUtils.formatDate_, DateUtils.formatDate);

        logger.info("创建新意指令,=======2=======workflowId={}-requestId={}-yhzh={}的收款方账号信息{}", workflowId, requestId, yhzh, JSON.toJSONString(skzh));
        logger.info("创建新意指令,=======3=======workflowId={}-requestId={}-fkzhzj={}的付款方账号信息{}", workflowId, requestId, fkzhzj, JSON.toJSONString(fkzh));

        paramDto.buildRecInfo(skzh.getYhzhmc(), skzh.getYhzh(), skzh.getKhyh(), "9999")
                .buildPayInfo(fkzh.getYhzhmc(), fkzh.getYhzh(), fkzh.getKhyh(), "9999")
                .buildDateInfo(date, date, date)
                .setOccurAmt(sqtbje).setNote(bz)
                .setPayBigBankAcc(yhzhh)
                .setRecBigBankAcc(skdezfh);
        callXinYi(workflowId, requestId, paramDto, jsonObj.getString("ID"), oaName, jsonObj.getString("HBTJ"), "股衍业务资金划拨流程");
    }

    public List<Fkzh> findByFkzhzjList(Set<String> set) {
        Map<String, Object> param = new HashMap<>();
        param.put("INSTR_yhzhzj", StringUtils.join(set, ","));
        List<Fkzh> list = fkzhRepo.findAll(SpecificationUtil.buildSpecification(param, Fkzh.class));


        List<Fkzh> res = Lists.newArrayList();
        Fkzh fkzh = new Fkzh();
        fkzh.setYhzh("32001614101052501685");
        fkzh.setYhzhmc("国联证券股份有限公司");
        fkzh.setYhzhzj("1001A5100000000005RA");
        fkzh.setKhyh("中国建设银行股份有限公司无锡太湖新城支行");
        res.add(fkzh);

        Fkzh fkzh1 = new Fkzh();
        fkzh1.setYhzh("32001618636052516617");
        fkzh1.setYhzhmc("国联证券股份有限公司");
        fkzh1.setYhzhzj("1001A5100000000005R4");
        fkzh1.setKhyh("中国建设银行股份有限公司无锡分行营业部");
        res.add(fkzh1);

        return res;
    }

    private void callGuShou(String workflowId, String requestId, String retStr, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        JSONArray detailMap3 = flowInfosJSONObject.getJSONArray("detailMap3");
        if (Objects.isNull(detailMap3)) {
            detailMap3 = flowInfosJSONObject.getJSONArray("detailMap");
        }
        if (CollectionUtils.isEmpty(detailMap3)) {
            String errMsg = MessageFormat.format("调用网关查询表单数据失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, retStr);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        detailMap3.forEach(obj -> {
            JSONObject jsonObj = (JSONObject) obj;
            String sqtbje = jsonObj.getString("SQTBJE");//金额
            String skzhzj = jsonObj.getString("SKZH");//账号
            Skzh skzh = skzhRepo.findByYhzhzj(skzhzj);
            if (skzh == null || skzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            // other信息
            String ykrq = jsonObj.getString("YKRQ");
            String bz = jsonObj.getString("BZ");
            String date = DateUtils.reFormatDate(ykrq, DateUtils.formatDate_, DateUtils.formatDate);
            // 付款信息
            String fkzhzj = jsonObj.getString("FKZH"); // 账户
            Fkzh fkzh = fkzhRepo.findByYhzhzj(fkzhzj);
            if (fkzh == null || fkzh.getYhzh() == null) {
                String errMsg = MessageFormat.format("不存在的银行账户，查询表单workflowId={0}-requestId={1}，账户主键：{2}", workflowId, requestId, skzhzj);
                logger.error(errMsg);
                throw GatewayException.error(errMsg);
            }
            paramDto
                    .buildRecInfo(skzh.getYhzhmc(), skzh.getYhzh(), skzh.getKhyh(), "9999")
                    .buildPayInfo(fkzh.getYhzhmc(), fkzh.getYhzh(), fkzh.getKhyh(), "9999")
                    .buildDateInfo(date, date, date)
                    .setOccurAmt(sqtbje).setNote(bz);

            callXinYi(workflowId, requestId, paramDto, jsonObj.getString("ID"), oaName, jsonObj.getString("HBTJ"), "固定收益部自有资金划拨流程");

        });
    }

    private void callGuShouYiJi(String workflowId, String requestId, XinYiParamDto paramDto, JSONObject flowInfosJSONObject, String oaName) {
        String zqqk = flowInfosJSONObject.getString("ZQQK");
        String jkje = flowInfosJSONObject.getString("JKJE");
        String skfzh = flowInfosJSONObject.getString("SKFZH");
        String skfzhkhh = flowInfosJSONObject.getString("SKFZHKHH");
        String skfdezfh = flowInfosJSONObject.getString("SKFDEZFH");
        String jksj = flowInfosJSONObject.getString("JKSJ");
        String date = DateUtils.reFormatDate(jksj, DateUtils.formatDate_, DateUtils.formatDate);
        String jkbzxx = flowInfosJSONObject.getString("JKBZXX");
        paramDto.buildRecInfo(skfzhkhh, skfzh, skfzhkhh, "9999")
                .setRecBigBankAcc(skfdezfh).buildDateInfo(date, date, date)
                .setOccurAmt(jkje).setNote(jkbzxx);
        if (StringUtils.isEmpty(zqqk) || !zqqk.equals("中签缴款")) {
            String errMsg = "客户未中签，不调用拨款流程";
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        if (StringUtils.isEmpty(jkje) || StringUtils.isEmpty(skfzh) || StringUtils.isEmpty(skfzhkhh)
                || StringUtils.isEmpty(jksj) || StringUtils.isEmpty(jkbzxx)) {
            String errMsg = "客户账户信息缺失， 无法调用拨款流程";
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
        callXinYi(workflowId, requestId, paramDto, null, oaName, null, "固定收益部债券-级申购流程");
    }

    private void callXinYi(String workflowId, String requestId, XinYiParamDto paramDto, String detailId, String oaName, String memo, String flowType) {
        paramDto.setOutInstId(requestId + "-" + System.currentTimeMillis());
        if (paramDto.getNote() == null) {
            paramDto.setNote("默认划款摘要");
        }
        String paramStr = JSON.toJSONString(paramDto);
        String ret = this.callXy(paramStr);
        JSONObject retObject = JSONObject.parseObject(ret);

        XinYiLog xinYiLog = new XinYiLog()
                .setRequestId(requestId)
                .setWorkflowId(workflowId)
                .setParam(paramStr)
                .setResult(ret)
                .setOaFlowName(oaName)
                .setDetailId(detailId)
                .setMemo(memo)
                .setRecBankAcc(paramDto.getRecBankAcc())
                .setRecBankAccName(paramDto.getRecBankAccName())
                .setPayBankAcc(paramDto.getPayBankAcc())
                .setPayBankAccName(paramDto.getPayBankAccName())
                .setStatus("Y")
                .setType(flowType)
                .setCreateTime(LocalDateTime.now())
                .setUpdateTime(LocalDateTime.now());
        if (StrUtil.isEmpty(ret) || null == retObject || null == retObject.get("code") || !GATEWAY_RET_CODE_SUCCESS.equals(retObject.get("code"))
                || Objects.isNull(retObject.getJSONObject("msg")) || !"0".equals(retObject.getJSONObject("msg").getString("retCode"))
        ) {
            xinYiLog.setStatus("N");
        }
        xinYiLogRepo.save(xinYiLog);
        if (StrUtil.isEmpty(ret) || null == retObject || null == retObject.get("code") || !GATEWAY_RET_CODE_SUCCESS.equals(retObject.get("code"))) {
            String errMsg = MessageFormat.format("调用网关新意付款流程失败，查询表单workflowId={0}-requestId={1}，接口返回异常：{2}", workflowId, requestId, ret);
            logger.error(errMsg);
            throw GatewayException.error(errMsg);
        }
    }


}
